<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	
</body>
<script>
	//观察者模式（也称发布-订阅模式）
	//通常会包含两类对象
	1，一个或多个发布者对象：当有重要的事情发生时会通知订阅者
	2，一个或多个订阅者对象：他们追随一个或多个发布者，监听他们的通知，并做出相应的反应
	//可以分为两类
	1，推送模式：由发布者负责将消息通知给各个订阅者
	2，拉动模式：要求订阅者主动跟踪发布者的变化
	//创建一个观察者对象，应该具备的属性和方法
	/*1，由回调函数构成的订阅者数组
	2，用于添加和删除订阅者的addSubscriber()和removeSubscriber()方法。
	3，publish()方法，接受并传递数据给订阅者
	4，make（）方法，将任意对象转变为一个发布者并为其添加上述方法*/
	var observer={
		addSubscriber:function(callback){
			if(typeof callback === 'function'){
				this.subscribers[this.subscribers.length]=callback;
			}
		},
		removeSubscriber:function(callback){
			for(var i=0;i<this.subscribers.length;i++){
				if(this.subscribers[i] === callback){
					delete this.subscribers[i];
				}
			}
		},
		publish:function(what){
			for(var i=0;i<this.subscribers.length;i++){
				if(typeof this.subscribers[i] === 'function'){
					this.subscribers[i](what);
				}
			}
		},
		make:function(o){
			for(var i in this){
				if(this.hasOwnProperty(i)){
					o[i]=this[i];
					o.subscribers=[];
				}
			}
		}

	}

	//创建订阅者，订阅者可以是任何对象，他们的唯一职责是在某些重要事情发生时调用publish（）方法
	//blogger，每当新博客准备好时，就会调用publish()方法
	var blogger={
		writeBlogPost:function(){
			var content='Today is '+new Date();
			this.publish(content);
		}
	}
	//la_times ,每当新一期的报刊出来时，就会调用publish()方法
	var la_times={
		newIssue:function(){
			var paper='Martians have landed on Earth!';
			this.publish(paper);
		}
	}

	//它们都很容易转变为发布者
	observer.make(blogger);
	observer.make(la_times);

	//准备两个简单的对象，用来测试
	var jack={
		read:function(what){
			console.log('I just read that'+what);
		}
	};
	var jill={
		gossip:function(what){
			console.log("You didn't hear it from me, but"+what);
		}
	};

	//他们可以订阅blogger对象，只需要提供事件发生时的回调函数
	blogger.addSubscriber(jack.read);
	blogger.addSubscriber(jill.gossip);

	blogger.writeBlogPost();

	//任何时候jill都可以取消订阅，当博主写了另外一篇博客时，jill将不会再收到通知
	blogger.removeSubscriber(jill.gossip);
	blogger.writeBlogPost();
	//jill也可以阅读la_times,因为一个订阅者可以对应多个发布者
	la_times.addSubscriber(jill.gossip);
	la_times.newIssue();
</script>
</html>